-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang][DebugInfo] Improve heuristic to determine whether to evaluate a static variable's initializer #72974
[clang][DebugInfo] Improve heuristic to determine whether to evaluate a static variable's initializer #72974
Conversation
@llvm/pr-subscribers-debuginfo @llvm/pr-subscribers-clang-codegen Author: Michael Buch (Michael137) ChangesThis patch extracts the logic to evaluate a C++ static data-member's constant initializer such that it can be used by an upcoming patch. It also makes the check for whether we are dealing with a constant initializer more robust/idiomatic, which revealed a bug in the Full diff: https://github.com/llvm/llvm-project/pull/72974.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0b52d99ad07f164..4c7c7d68b4271e3 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -69,6 +69,29 @@ static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
}
+/// Given a VarDecl corresponding to either the definition or
+/// declaration of a C++ static data member, if it has a constant
+/// initializer and is evaluatable, return the evaluated value.
+/// Returns std::nullopt otherwise.
+static std::optional<APValue>
+evaluateConstantInitializer(const clang::VarDecl *VD,
+ const clang::ASTContext &Ctx) {
+ assert(VD != nullptr);
+
+ if (!VD->isStaticDataMember())
+ return std::nullopt;
+
+ if (!VD->isUsableInConstantExpressions(Ctx))
+ return std::nullopt;
+
+ auto const *InitExpr = VD->getAnyInitializer();
+ Expr::EvalResult Result;
+ if (!InitExpr->EvaluateAsConstantExpr(Result, Ctx))
+ return std::nullopt;
+
+ return Result.Val;
+}
+
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -5596,14 +5619,11 @@ void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) {
if (VD->hasAttr<NoDebugAttr>())
return;
- if (!VD->hasInit())
- return;
-
const auto CacheIt = DeclCache.find(VD);
if (CacheIt != DeclCache.end())
return;
- auto const *InitVal = VD->evaluateValue();
+ const auto InitVal = evaluateConstantInitializer(VD, CGM.getContext());
if (!InitVal)
return;
diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
index f2d4d9408a8297a..6ba98373d33ada8 100644
--- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
@@ -67,10 +67,6 @@ int main() {
// CHECK-SAME: flags: DIFlagStaticMember
// CHECK-NOT: extraData:
-// CHECK: ![[IENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "inline_enum",
-// CHECK-SAME: flags: DIFlagStaticMember
-// CHECK-NOT: extraData:
-
// CHECK: ![[EMPTY_TEMPLATED_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "empty_templated",
// CHECK-SAME: flags: DIFlagStaticMember
// CHECK-NOT: extraData:
@@ -98,11 +94,6 @@ int main() {
// CHECK-NOT: linkageName:
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]])
-// CHECK: !DIGlobalVariableExpression(var: ![[IENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
-// CHECK: ![[IENUM_VAR]] = distinct !DIGlobalVariable(name: "inline_enum"
-// CHECK-NOT: linkageName:
-// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[IENUM_DECL]])
-
// CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_TEMPLATED_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
// CHECK: ![[EMPTY_TEMPLATED_VAR]] = distinct !DIGlobalVariable(name: "empty_templated"
// CHECK-NOT: linkageName:
|
@llvm/pr-subscribers-clang Author: Michael Buch (Michael137) ChangesThis patch extracts the logic to evaluate a C++ static data-member's constant initializer such that it can be used by an upcoming patch. It also makes the check for whether we are dealing with a constant initializer more robust/idiomatic, which revealed a bug in the Full diff: https://github.com/llvm/llvm-project/pull/72974.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0b52d99ad07f164..4c7c7d68b4271e3 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -69,6 +69,29 @@ static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
}
+/// Given a VarDecl corresponding to either the definition or
+/// declaration of a C++ static data member, if it has a constant
+/// initializer and is evaluatable, return the evaluated value.
+/// Returns std::nullopt otherwise.
+static std::optional<APValue>
+evaluateConstantInitializer(const clang::VarDecl *VD,
+ const clang::ASTContext &Ctx) {
+ assert(VD != nullptr);
+
+ if (!VD->isStaticDataMember())
+ return std::nullopt;
+
+ if (!VD->isUsableInConstantExpressions(Ctx))
+ return std::nullopt;
+
+ auto const *InitExpr = VD->getAnyInitializer();
+ Expr::EvalResult Result;
+ if (!InitExpr->EvaluateAsConstantExpr(Result, Ctx))
+ return std::nullopt;
+
+ return Result.Val;
+}
+
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -5596,14 +5619,11 @@ void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) {
if (VD->hasAttr<NoDebugAttr>())
return;
- if (!VD->hasInit())
- return;
-
const auto CacheIt = DeclCache.find(VD);
if (CacheIt != DeclCache.end())
return;
- auto const *InitVal = VD->evaluateValue();
+ const auto InitVal = evaluateConstantInitializer(VD, CGM.getContext());
if (!InitVal)
return;
diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
index f2d4d9408a8297a..6ba98373d33ada8 100644
--- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
@@ -67,10 +67,6 @@ int main() {
// CHECK-SAME: flags: DIFlagStaticMember
// CHECK-NOT: extraData:
-// CHECK: ![[IENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "inline_enum",
-// CHECK-SAME: flags: DIFlagStaticMember
-// CHECK-NOT: extraData:
-
// CHECK: ![[EMPTY_TEMPLATED_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "empty_templated",
// CHECK-SAME: flags: DIFlagStaticMember
// CHECK-NOT: extraData:
@@ -98,11 +94,6 @@ int main() {
// CHECK-NOT: linkageName:
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]])
-// CHECK: !DIGlobalVariableExpression(var: ![[IENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
-// CHECK: ![[IENUM_VAR]] = distinct !DIGlobalVariable(name: "inline_enum"
-// CHECK-NOT: linkageName:
-// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[IENUM_DECL]])
-
// CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_TEMPLATED_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
// CHECK: ![[EMPTY_TEMPLATED_VAR]] = distinct !DIGlobalVariable(name: "empty_templated"
// CHECK-NOT: linkageName:
|
This patch extracts the logic to evaluate a C++ static data-member's constant initializer such that it can be used by an upcoming patch. It also makes the check for whether we are dealing with a constant initializer more robust/idiomatic, which revealed a bug in the `debug-info-static-inline-member` test.
4bb7f6b
to
0120962
Compare
…fo-static-inline-member The check for this was removed in llvm#72974 This patch removes the member from the source itself since it was confusing FileCheck
Test fix in flight... |
…fo-static-inline-member The check for this was removed in #72974 This patch removes the member from the source itself since it was confusing FileCheck
This patch extracts the logic to evaluate a C++ static data-member's constant initializer. This logic will be re-used in an upcoming patch.
It also makes the check for whether we are dealing with a constant initializer more robust/idiomatic, which revealed a bug in the
debug-info-static-inline-member
test (which existed since its introduction in #71780)Test changes
debug-info-static-member.cpp
:const_b
as part of thepatch series in
638a8393615e911b729d5662096f60ef49f1c65e
.The check for
isUsableAsConstantExpression
added in the current patchdoesn't support constant inline floats (since they are neither constexpr nor
integrals). This isn't a regression since before said patch series
we wouldn't ever emit the definition for
const_b
anyway. Nowwe just don't do it for
inline const float
s. This is consistent withGCC's behaviour starting with C++11.
debug-info-static-inline-member
:a
DW_AT_const_value
for a non-const static.